Repository navigation
[3/3] feat!: remove personal squads, consult mode and the global squad; project-only resolution; F6/F7/F8 - #2279
Conversation
🔴 Impact Analysis — PR #2279Risk tier: 🔴 CRITICAL 📊 Summary
🎯 Risk Factors
📦 Modules Affectedci-workflows (1 file)
docs (14 files)
root (12 files)
squad-cli (28 files)
squad-sdk (18 files)
templates (4 files)
tests (37 files)
|
🛫 PR Readiness Check
PR Scope: 📦🔧 Mixed (product + infrastructure)
|
| Status | Check | Details |
|---|---|---|
| ❌ | Single commit | 8 commits — consider squashing before review |
| ✅ | Not in draft | Ready for review |
| ✅ | Branch up to date | Up to date with squad2-b-upstream-runtime |
| ❌ | Copilot review | No Copilot review yet — it may still be processing |
| ✅ | Changeset present | Changeset file found |
| ✅ | Scope clean | No .squad/ or docs/proposals/ files |
| ✅ | No merge conflicts | No merge conflicts |
| ✅ | Copilot threads resolved | 0 active Copilot thread(s) resolved (6 outdated skipped) |
| ❌ | CI passing | 2 check(s) failing: samples-build, test |
Files Changed (114 files, +2117 −7931)
| File | +/− |
|---|---|
.changeset/squad2-c-personal-removal-and-fixes.md |
+12 −0 |
.github/agents/squad.agent.md |
+1 −26 |
.squad-templates/README.md |
+1 −1 |
.squad-templates/skills/personal-squad/SKILL.md |
+0 −66 |
.squad-templates/spawn-reference.md |
+0 −12 |
.squad-templates/squad.agent.md |
+1 −26 |
README.md |
+2 −2 |
README.zh.md |
+2 −2 |
docs/src/content/docs/concepts/squad-2-0-architecture.md |
+1 −1 |
docs/src/content/docs/features/consult-mode.md |
+0 −260 |
docs/src/content/docs/get-started/installation.md |
+2 −17 |
docs/src/content/docs/guide.md |
+0 −1 |
docs/src/content/docs/guide/personal-squad.md |
+0 −350 |
docs/src/content/docs/reference/api-reference.md |
+2 −2 |
docs/src/content/docs/reference/cli.md |
+4 −4 |
docs/src/content/docs/reference/config.md |
+5 −4 |
docs/src/content/docs/reference/host-feature-matrix.md |
+19 −19 |
docs/src/content/docs/reference/sdk.md |
+2 −4 |
docs/src/content/docs/scenarios/upgrading.md |
+10 −0 |
docs/src/content/docs/scenarios/using-squad-across-clients.md |
+0 −1 |
docs/src/content/docs/whatsnew.md |
+3 −0 |
docs/src/navigation.ts |
+0 −2 |
packages/squad-cli/README.md |
+4 −4 |
packages/squad-cli/package.json |
+0 −8 |
packages/squad-cli/src/cli-entry.ts |
+28 −79 |
packages/squad-cli/src/cli/commands/cast.ts |
+19 −77 |
packages/squad-cli/src/cli/commands/config.ts |
+6 −13 |
packages/squad-cli/src/cli/commands/consult.ts |
+0 −103 |
packages/squad-cli/src/cli/commands/copilot.ts |
+2 −1 |
packages/squad-cli/src/cli/commands/doctor.ts |
+7 −1 |
packages/squad-cli/src/cli/commands/economy.ts |
+6 −14 |
packages/squad-cli/src/cli/commands/export.ts |
+2 −2 |
packages/squad-cli/src/cli/commands/externalize.ts |
+1 −1 |
packages/squad-cli/src/cli/commands/extract.ts |
+0 −332 |
packages/squad-cli/src/cli/commands/loop.ts |
+2 −2 |
packages/squad-cli/src/cli/commands/migrate.ts |
+3 −3 |
packages/squad-cli/src/cli/commands/notes.ts |
+2 −2 |
packages/squad-cli/src/cli/commands/personal.ts |
+0 −248 |
packages/squad-cli/src/cli/commands/state-mcp.ts |
+1 −0 |
packages/squad-cli/src/cli/commands/upstream.ts |
+2 −2 |
packages/squad-cli/src/cli/commands/watch/index.ts |
+2 −2 |
packages/squad-cli/src/cli/core/command-help.ts |
+3 −30 |
packages/squad-cli/src/cli/core/errors.ts |
+12 −0 |
packages/squad-cli/src/cli/core/init.ts |
+3 −45 |
packages/squad-cli/src/cli/core/upgrade.ts |
+77 −8 |
packages/squad-cli/src/cli/shell/index.ts |
+4 −35 |
packages/squad-cli/templates/README.md |
+1 −1 |
packages/squad-cli/templates/skills/personal-squad/SKILL.md |
+0 −66 |
packages/squad-cli/templates/spawn-reference.md |
+0 −12 |
packages/squad-cli/templates/squad.agent.md.template |
+1 −26 |
| ... | +64 more files |
Total: +2117 −7931
This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.
🏗️ Architectural Review
Automated architectural review — informational only. |
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved profile-boundary, macOS isolation, upgrade-safety, and release-gate defects prevent approval.
6 open issues
Allow consumed changeset fragments in drift checks · New Require resolver admission before doctor runs · New Handle null config values during upgrade preflight · New Preserve non-version text when normalizing template versions · New Seed the child CLI's actual macOS config path · New Isolate macOS global config and home paths in tests · New
What changed in this PR
The final layer of the Squad 2.0 stack removes profile-level squads in favor of project-only resolution, building on the host capability matrix and runtime upstream inheritance work.
Changes:
- Removes personal/global squad commands, SDK APIs, coordinator instructions, templates, and documentation.
- Adds project-boundary, upgrade, profile-isolation, and retired-symbol regression checks.
- Fixes state-backend reporting and root listing, and declares Claude Code background-run support.
| File | Description |
|---|---|
vitest.config.ts |
Registers the test profile guard. |
test/upgrade-profile-teamroot.test.ts |
Tests stale links and upgrade backup preservation. |
test/template-extra-classification.test.ts |
Removes retired template exceptions. |
test/standalone-release-workflow.test.ts |
Removes the deleted guide from documentation checks. |
test/squad-20-pack-smoke.test.ts |
Removes the retired environment switch. |
test/squad-20-host-feature-matrix.test.ts |
Verifies backend reporting and root listing fixes. |
test/squad-20-all-scenarios.e2e.test.ts |
Updates Claude background-run expectations. |
test/setup/profile-guard.ts |
Redirects test profile paths to temporary directories. |
test/sdk-feature-parity.test.ts |
Removes consult-mode API tests. |
test/retired-symbols.test.ts |
Adds source, export, and package retirement checks. |
test/resolve-cache.test.ts |
Removes multi-squad cache tests. |
test/resolution.test.ts |
Removes personal-directory creation tests. |
test/repl-ux-e2e.test.ts |
Updates profile-isolation comments. |
test/init-vscode-settings.test.ts |
Removes global-init expectations. |
test/external-state.test.ts |
Uses neutral configuration fields in preservation tests. |
test/docs-build.test.ts |
Removes deleted pages from expected documentation. |
test/cross-package-exports.test.ts |
Removes retired SDK export expectations. |
test/cli/extract.test.ts |
Deletes extract-command tests. |
test/cli/consult.test.ts |
Deletes consult-command tests. |
test/cli/command-help.test.ts |
Removes retired commands from help expectations. |
test/cli/cast.test.ts |
Removes personal-agent mocks. |
test/cli-packaging-smoke.test.ts |
Removes retired command checks. |
test/cli-outside-project.test.ts |
Tests project-only errors and rejected global flags. |
test/cli-global.test.ts |
Deletes global-routing tests. |
test/acceptance/features/extract-command.feature |
Deletes extract acceptance scenarios. |
test/acceptance/features/consult-command.feature |
Deletes consult acceptance scenarios. |
test/acceptance/acceptance.test.ts |
Stops registering deleted feature scenarios. |
test-fixtures/spec/suite-v0.2/host-feature-matrix.json |
Updates capability status and bridge evidence. |
test-fixtures/spec/suite-v0.2/capability-matrix.json |
Declares Claude background-run support. |
templates/squad.agent.md.template |
Removes personal-agent discovery and routing. |
templates/spawn-reference.md |
Removes Ghost Protocol spawn instructions. |
templates/skills/personal-squad/SKILL.md |
Deletes the retired skill mirror. |
templates/README.md |
Updates the spawn-reference description. |
templates/personal-charter.md |
Deletes the personal-agent charter template. |
templates/ghost-protocol.md |
Deletes Ghost Protocol documentation. |
README.zh.md |
Removes global-init and upgrade guidance. |
README.md |
Removes global-init and upgrade guidance. |
packages/squad-sdk/templates/squad.agent.md.template |
Mirrors project-only coordinator instructions. |
packages/squad-sdk/templates/spawn-reference.md |
Removes Ghost Protocol instructions. |
packages/squad-sdk/templates/skills/personal-squad/SKILL.md |
Deletes the SDK skill mirror. |
packages/squad-sdk/templates/README.md |
Updates the spawn-reference description. |
packages/squad-sdk/src/types.ts |
Removes multi-squad type exports. |
packages/squad-sdk/src/tools/index.ts |
Reports backend name and team directory. |
packages/squad-sdk/src/state-backend.ts |
Maps the state root to an empty key. |
packages/squad-sdk/src/sharing/index.ts |
Removes consult exports. |
packages/squad-sdk/src/multi-squad.ts |
Deletes the profile-level squad registry. |
packages/squad-sdk/src/config/init.ts |
Removes extraction configuration. |
packages/squad-sdk/src/client/adapters/capabilities.ts |
Adds Claude background-run capability. |
packages/squad-sdk/src/agents/personal.ts |
Deletes personal-agent discovery and merging. |
packages/squad-sdk/src/agents/index.ts |
Removes personal-agent exports. |
packages/squad-sdk/README.md |
Updates the resolution API summary. |
packages/squad-sdk/package.json |
Removes the personal-agent subpath export. |
packages/squad-cli/templates/squad.agent.md.template |
Mirrors project-only coordinator instructions. |
packages/squad-cli/templates/spawn-reference.md |
Removes Ghost Protocol instructions. |
packages/squad-cli/templates/skills/personal-squad/SKILL.md |
Deletes the CLI skill mirror. |
packages/squad-cli/templates/README.md |
Updates the spawn-reference description. |
packages/squad-cli/src/cli/shell/index.ts |
Removes profile fallback and consult reminders. |
packages/squad-cli/src/cli/core/upgrade.ts |
Cleans stale links and normalizes version stamps. |
packages/squad-cli/src/cli/core/init.ts |
Removes personal-squad linking and global options. |
packages/squad-cli/src/cli/core/command-help.ts |
Removes retired commands and flags. |
packages/squad-cli/src/cli/commands/state-mcp.ts |
Passes the backend name to state tools. |
packages/squad-cli/src/cli/commands/personal.ts |
Deletes personal-squad management. |
packages/squad-cli/src/cli/commands/extract.ts |
Deletes learning extraction. |
packages/squad-cli/src/cli/commands/externalize.ts |
Updates a configuration-preservation comment. |
packages/squad-cli/src/cli/commands/doctor.ts |
Adds an outside-project admission check. |
packages/squad-cli/src/cli/commands/consult.ts |
Deletes consult-mode setup. |
packages/squad-cli/src/cli/commands/cast.ts |
Displays project agents only. |
packages/squad-cli/src/cli-entry.ts |
Removes retired routing and rejects global flags. |
packages/squad-cli/README.md |
Documents project-only resolution. |
packages/squad-cli/package.json |
Removes retired command exports. |
docs/src/navigation.ts |
Removes retired documentation links. |
docs/src/content/docs/whatsnew.md |
Records breaking changes and bridge fixes. |
docs/src/content/docs/scenarios/using-squad-across-clients.md |
Removes obsolete profile-link troubleshooting. |
docs/src/content/docs/scenarios/upgrading.md |
Documents cleanup and downgrade limitations. |
docs/src/content/docs/reference/sdk.md |
Removes personal-state API guidance. |
docs/src/content/docs/reference/config.md |
Documents project-only discovery. |
docs/src/content/docs/reference/cli.md |
Removes global-init guidance and fallback order. |
docs/src/content/docs/reference/api-reference.md |
Clarifies the config directory’s remaining purpose. |
docs/src/content/docs/guide/personal-squad.md |
Deletes the personal-squad guide. |
docs/src/content/docs/guide.md |
Removes the global-init command row. |
docs/src/content/docs/get-started/installation.md |
Removes profile setup instructions. |
docs/src/content/docs/features/consult-mode.md |
Deletes consult-mode documentation. |
docs/src/content/docs/concepts/squad-2-0-architecture.md |
Updates Claude capability documentation. |
.squad-templates/squad.agent.md |
Removes canonical personal-agent instructions. |
.squad-templates/spawn-reference.md |
Removes canonical Ghost Protocol instructions. |
.squad-templates/skills/personal-squad/SKILL.md |
Deletes the canonical retired skill. |
.squad-templates/README.md |
Updates the canonical reference description. |
.github/agents/squad.agent.md |
Mirrors the coordinator instruction removals. |
.changeset/squad2-c-personal-removal-and-fixes.md |
Declares major releases and breaking changes. |
Review effort: Balanced
…ormalization, tolerant teamRoot preflight [3/3] Copilot review threads on #2279: - doctor: the resolver is the single admission check (a bare ./.squad existence check let `squad doctor` run from the home directory against ~/.squad); test now also runs every outside-project command directly from the seeded home dir (red pre-fix for doctor). - upgrade: the stale-teamRoot preflight tolerates null/array/scalar config.json like readSquadConfig (test); stripAgentStamps normalizes only the version token on the `- **Version:**` line so an edited instruction is still a customization (test). - resolveGlobalSquadPath honours XDG_CONFIG_HOME on macOS as well, so the test profile guard (and the outside-project test, which no longer overrides HOME) isolates macOS too. - retired-symbols gate: validates the changeset fragment only while it exists (changeset version consumes it); post-release it requires the sentence in the CLI CHANGELOG; the whatsnew/upgrading exactly-once checks stay durable. - cast: outside-project message aligned with status/doctor ("No squad in this directory (searched from ...). Run "squad init" here, or use --team-root ..."). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
52c467c to
21ecca7
Compare
…ormalization, tolerant teamRoot preflight [3/3] Copilot review threads on #2279: - doctor: the resolver is the single admission check (a bare ./.squad existence check let `squad doctor` run from the home directory against ~/.squad); test now also runs every outside-project command directly from the seeded home dir (red pre-fix for doctor). - upgrade: the stale-teamRoot preflight tolerates null/array/scalar config.json like readSquadConfig (test); stripAgentStamps normalizes only the version token on the `- **Version:**` line so an edited instruction is still a customization (test). - resolveGlobalSquadPath honours XDG_CONFIG_HOME on macOS as well, so the test profile guard (and the outside-project test, which no longer overrides HOME) isolates macOS too. - retired-symbols gate: validates the changeset fragment only while it exists (changeset version consumes it); post-release it requires the sentence in the CLI CHANGELOG; the whatsnew/upgrading exactly-once checks stay durable. - cast: outside-project message aligned with status/doctor ("No squad in this directory (searched from ...). Run "squad init" here, or use --team-root ..."). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
2a67ab6 to
fd37c4b
Compare
…ormalization, tolerant teamRoot preflight [3/3] Copilot review threads on #2279: - doctor: the resolver is the single admission check (a bare ./.squad existence check let `squad doctor` run from the home directory against ~/.squad); test now also runs every outside-project command directly from the seeded home dir (red pre-fix for doctor). - upgrade: the stale-teamRoot preflight tolerates null/array/scalar config.json like readSquadConfig (test); stripAgentStamps normalizes only the version token on the `- **Version:**` line so an edited instruction is still a customization (test). - resolveGlobalSquadPath honours XDG_CONFIG_HOME on macOS as well, so the test profile guard (and the outside-project test, which no longer overrides HOME) isolates macOS too. - retired-symbols gate: validates the changeset fragment only while it exists (changeset version consumes it); post-release it requires the sentence in the CLI CHANGELOG; the whatsnew/upgrading exactly-once checks stay durable. - cast: outside-project message aligned with status/doctor ("No squad in this directory (searched from ...). Run "squad init" here, or use --team-root ..."). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
…ject-only resolution; state-bridge fixes [3/3] BREAKING: Personal squads, consult mode and the global squad (`--global`) were removed; existing `personal-squad/` and global `.squad/` directories under the user profile are no longer read or written and may be deleted manually. Squad 2.0 keeps exactly one place for a team: the project `.squad/`. This removes every trace of the 1.x profile-level features from the product and the docs, with one line of history in the changeset. Removed - CLI: `squad personal|consult|extract`, `--global` on init/upgrade, the user-profile fallback in `squad status`/`squad cost`/the shell, `--legacy-personal` import, the `SQUAD_NO_PERSONAL`/`SQUAD_PERSONAL_DIR` switches, init `teamRoot` auto-link, the `multi-squad` registry. - SDK: `agents/personal`, `sharing/consult`, `resolvePersonalSquadDir`, `ensurePersonalSquadDir`, `ensureSquadPathTriple`, `isConsultMode`, `ResolvedSquadPaths.personalDir`, `SquadDirConfig.consult`/`extractionDisabled`, `InitOptions.extractionDisabled`/`isGlobal`, `multi-squad.ts` and its types. `resolveGlobalSquadPath()` stays only as the base of externalized project state. - Coordinator: Personal Squad / Consult Mode / Ghost Protocol sections and routing rows in the canonical agent and all host digests; personal-squad skill, ghost-protocol and personal-charter templates; docs pages, nav, README rows, whatsnew/upgrading mentions, the retired matrix row. Dead tests for the removed surface. Behaviour - Squad resolves `.squad/` only from the current directory and its parents. Outside a project `squad status`, `squad doctor`, `squad cast` and `squad cost` fail with "No squad in this directory … run squad init" instead of resolving a profile dir. - Nothing ever reads, writes, moves or deletes the 1.x directories. State-bridge fixes (Data F6/F7/F8) - `squad_state_health` reports `State backend: local|orphan|two-layer`, storage class and team squad dir (`ToolRegistry` accepts `backendName`); `squad_state_list` without `dir` lists the root on git-backed backends; Claude Code declares `background-runs` in `capability-matrix.json` and `CAPABILITY_TOKENS_BY_HOST`; matrix cells/notes updated. Tests - test/retired-symbols.test.ts: CI gate grepping every tracked file and the built dist for the retired names/phrases, with an explicit allowlist (the changeset BREAKING line, CHANGELOGs, pre-2.0 whatsnew history, a contributor credit, the two tombstone tests). - test/profile-squad-tombstone.test.ts: a seeded 1.x profile tree (personal-squad/ + global .squad/) stays sha256-identical and is never touched by any fs/storage call through init -> cast -> upgrade x2 -> client install/rollback; roster lands in the project; teamRoot never set; two side-by-side projects independent; no fallback. - test/cli-outside-project.test.ts: built CLI in an empty repo with a seeded profile squad: status/doctor/cast/cost exit non-zero with the remediation message, never mention or touch the profile squad; status inside a project still works. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
…rune retired exports; guard tests from the real profile [3/3] Worf Layer C review (LC-1..6) and the test-profile incident: - LC-2 (data integrity): both squad-dir walkers (resolveSquad, resolveSquadPaths/ findSquadDir) stop at the home directory and never accept ~/.squad or SQUAD_HOME as a project squad, so `squad cast` from a directory without a repo marker can no longer write into the profile. Tests: tombstone unit test (fake HOME/USERPROFILE/SQUAD_HOME, no .git, zero fs hits) and a built-CLI test (cast/status/doctor/cost fail with the remediation message, fake profile sha256-identical) — verified red pre-fix (`Added agent Probe` under fake-home/.squad). - LC-3: `--global` on any command fails with `Unknown option: --global` (exit 1) instead of silently running the project form; test for init/upgrade. - LC-1: `./commands/extract` and `./commands/personal` exports removed from the CLI package.json; the retired-symbol gate now scans both manifests' `exports` (retired names + every target must exist in dist; the pre-existing dangling `./shell/sdk-bridge` is listed as known) and the `npm pack --dry-run` file lists. - Incident: new vitest setupFile `test/setup/profile-guard.ts` redirects SQUAD_HOME, APPDATA, LOCALAPPDATA and XDG_CONFIG_HOME into a per-worker temp dir before any test loads, so no test can read or write the real profile (HOME/USERPROFILE untouched so git/gh keep working; the walker fix covers ~/.squad). - LC-4: squad-home docs no longer speak of "personal agents". LC-5: the single BREAKING sentence is repeated verbatim once in whatsnew v2.0.0 and the upgrading guide (gate enforces exactly once, nothing else). LC-6: `health` help line shortened. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
…zation check [3/3] Data's upgrade matrix (#2282) findings UM-F1 and UM-F2: - UM-F1: projects initialized by 0.13-1.1 while a profile squad existed carry `teamRoot: "<platform-config>/squad"`. `isRetiredProfileTeamRoot()` (SDK) recognises the platform config dir, `~/.squad`, `SQUAD_HOME` and the home dir; `resolveSquadPaths` never follows such a teamRoot (local mode), and `squad upgrade` removes the key with one neutral line ("Removed stale teamRoot pointing to <path>; project state is now local"; --dry-run only announces). A genuine dual-root teamRoot (another repo) is preserved. - UM-F2: `stripAgentStamps()` normalizes every stamp form the upgrader writes (`<!-- version: X -->`, `- **Version:** X`, `Squad vX`, `@bradygaster/squad-cli@X`, legacy `<!-- squad-cli vX -->`) before comparing squad.agent.md with the template, and an existing `.local-backup` holding the same bytes is not rewritten. - Docs: upgrading guide notes both and adds "Downgrading and old CLIs" guidance. - Tests: test/upgrade-profile-teamroot.test.ts (6) — both findings verified red against the pre-fix SDK/CLI (remote mode; "local customizations" warning on pass 1). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
…ormalization, tolerant teamRoot preflight [3/3] Copilot review threads on #2279: - doctor: the resolver is the single admission check (a bare ./.squad existence check let `squad doctor` run from the home directory against ~/.squad); test now also runs every outside-project command directly from the seeded home dir (red pre-fix for doctor). - upgrade: the stale-teamRoot preflight tolerates null/array/scalar config.json like readSquadConfig (test); stripAgentStamps normalizes only the version token on the `- **Version:**` line so an edited instruction is still a customization (test). - resolveGlobalSquadPath honours XDG_CONFIG_HOME on macOS as well, so the test profile guard (and the outside-project test, which no longer overrides HOME) isolates macOS too. - retired-symbols gate: validates the changeset fragment only while it exists (changeset version consumes it); post-release it requires the sentence in the CLI CHANGELOG; the whatsnew/upgrading exactly-once checks stay durable. - cast: outside-project message aligned with status/doctor ("No squad in this directory (searched from ...). Run "squad init" here, or use --team-root ..."). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
…acceptance/portability expectations for 2.0 [3/3] CI on 21ecca7 (ubuntu) — all branch-caused, all from the last two commits: - Profile boundary compared `os.homedir()` with the walk's current path textually; on Windows `os.tmpdir()` yields the 8.3 form (`C:\Users\SOMEUS~1\...`) so the boundary was missed and `squad status` from a temp dir resolved `~/.squad` (acceptance saw `Path: C:\Users\TAMIRD~1\.squad`). Boundary comparisons now use `realpathSync.native` on the longest existing prefix (`canonicalDir`); callers still get paths in their own spelling (resolve-cache tests unchanged). - test/setup/profile-guard.ts: SQUAD_HOME is redirected to `<guard>/home/.squad` so the path keeps its real shape (comms-teams tests assert the `.squad` segment). - acceptance features: outside a project `squad status`/`squad doctor` now fail with "No squad in this directory … squad init" (exit 1) — the 2.0 contract, replacing the old fallback expectations. - cli/upgrade-portability: the fixture asserted the UM-F2 bug (a stamp/CRLF-only delta produced a .local-backup); it now applies a genuine local edit, which is still backed up. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
…-closed canonicalization, fs guard, one-pass 0.9.x upgrade [3/3] Q/Bubu/Worf conditions on Layer C: - LC-9: one message for every project-scoped command, from `NO_SQUAD_MESSAGE` / `fatalNoSquad()`: `No squad in this directory. Run "squad init" first.` (status, doctor, cast, cost, upgrade, nap, export, notes, upstream, economy, config, loop, watch, migrate, copilot). economy/config used private walkers that reached ~/.squad — replaced by the SDK resolver. Test runs 11 commands from an empty repo, asserts the identical line, exit 1, and that nothing (no .squad mkdir) is created. - LC-11: the platform config dir (%APPDATA%\squad, ~/.config/squad, ~/Library/…/squad) is part of the profile boundary: a `.squad` at or under it is never admitted (any spelling), and the boundary is established by canonicalizing only the PARENT so the retired directory itself is never stat'ed. - LC-12: canonicalization is fail-closed — `canonicalDir` returns null when the existing prefix cannot be realpath'ed and callers refuse (resolver returns null, teamRoot treated as retired) instead of comparing lexically; an unknown home dir also refuses. A link named `.squad` whose target is profile-owned is refused too. - Fail-closed test guard: `test/setup/profile-fs-guard.cjs` wraps fs/fs.promises (sync, callback, promise) and THROWS on any access under the real profile roots; loaded by the vitest setup file from the original environment and inherited by child processes via NODE_OPTIONS=--require + SQUAD_TEST_FORBIDDEN_ROOTS. test/profile-fs-guard.test.ts proves a deliberate access throws in-process and in a child with faked HOME/APPDATA. - Projects under the profile keep working: test/profile-boundary.test.ts covers <home>/src/proj, long/8.3 paths (skips loudly when 8.3 is disabled), case/separator variants, a junction to the profile root, SQUAD_HOME/APPDATA/HOME/USERPROFILE variants. - F4 (Data, upgrade matrix): the casting pair is ensured BEFORE squad.agent.md is rendered, so a 0.9.x project (empty casting/) gets the capabilities block on the first upgrade and the second upgrade is a byte-identical no-op. - Eradication boundary: the teamRoot cleanup prints `Removed obsolete "teamRoot" setting from .squad/config.json.` (no path). - Single historical record: the BREAKING sentence lives only in whatsnew v2.0.0; the upgrading guide links to that section; the retired-symbol gate enforces both. LC-9 equality, LC-11, LC-12 and F4 tests verified red against the pre-fix code. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
…ev by #2285) [3/3] Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
fd37c4b to
94e7675
Compare


What
Layer 3/3 of the Squad 2.0 pre-preview follow-up stack (base: #2278 ← #2277). Full eradication of the 1.x profile-level features — personal squads, consult mode, Ghost Protocol and the global squad (
--global) — from product, templates, skills, docs and help; squad resolution becomes project-only with clear errors outside a project; the state-bridge fixes F6/F7/F8; a CI retired-symbol gate and tombstone tests proving the removed directories are never touched.Why
Brady: "eradicate the whole idea of personal squads from the product, the docs — everywhere. no trace left." Tamir extended this to the global squad; Q/Bubu agreed it simplifies the ship. Finding F9 (1.x
squad initsilently pointed new projects'teamRootat%APPDATA%\squad/~/.config/squad) is resolved by removing the concept rather than patching it. Q additionally required a CI denylist test and that outside-project state commands fail clearly instead of falling back; Bubu required the negative regression (no reads/writes/moves/deletes of legacy dirs) as a tombstone.How
squad personal|consult|extract;--globaloninit/upgrade; the user-profile fallback insquad status,squad costand the interactive shell;--legacy-personalimport and the one-time notices (no migration code at all per the decision);SQUAD_NO_PERSONAL/SQUAD_PERSONAL_DIR; initteamRootauto-link; the unusedmulti-squadregistry (squads.json). Unknown subcommands get the normal unknown-command behaviour.agents/personal,sharing/consult,resolvePersonalSquadDir,ensurePersonalSquadDir,ensureSquadPathTriple,isConsultMode,ResolvedSquadPaths.personalDir,SquadDirConfig.consult/extractionDisabled,InitOptions.extractionDisabled/isGlobal,multi-squad.ts+ its types.resolveGlobalSquadPath()remains only as the base of externalized project state (squad externalize→<config>/squad/projects/<key>), documented as such.personal-squadskill,ghost-protocol.md,personal-charter.mdtemplates and their mirrors (sync-templates).guide/personal-squad,features/consult-mode, nav entries, README/README.zh rows, installation "Optional: Global squad", CLI/config/SDK resolution-order items, upgrading/whatsnew mentions, the retired matrix row. Resolution order now: current dir → parents; never a user-profile dir..squad/in the tree)squad status,squad doctor,squad cast,squad costfail withNo squad in this directory (searched from …). Run "squad init" …(exit ≠ 0).init/upgradeonly ever write inside the project.squad/. No code reads, writes, moves or deletespersonal-squad/or a profile.squad/.squad_state_health→State backend: local|orphan|two-layer+ storage class + team squad dir (ToolRegistrybackendName);squad_state_listwithoutdirlists the root on git-backed backends; Claude Code declaresbackground-runsincapability-matrix.json/CAPABILITY_TOKENS_BY_HOST(+ matrix runtime flag, cells and notes; the formerit.failsfor F6/F8 flipped).test/retired-symbols.test.tsenforces that nothing else names the retired concepts.Requirements → tests
test/retired-symbols.test.ts› "tracked files …", "built dist/ output that ships in the npm tarballs", "the allowlisted files still exist and the BREAKING entry is exactly one line". Allowlist: the changeset, CHANGELOGs (release history), whatsnew sections ≤ v1.1.0 (history; v2.0.0 section is scanned),guide/contributors.md(a PR #198 credit line), the two tombstone tests, the gate itself. Also verifiednpm pack --dry-runlists no retired files.teamRootnever set; multi-project independencetest/profile-squad-tombstone.test.ts› "init → cast → upgrade ×2 → client install/rollback leaves the 1.x profile tree sha256-identical, never touches it, and populates the project roster" (seededpersonal-squad/and global.squad/; everynode:fsandFSStorageProvidercall watched for paths under the profile root ⇒ zero hits), "two projects initialised side by side … are independent", "a directory without .squad/ never resolves to the profile squad"test/cli-outside-project.test.ts(built CLI, empty git repo, seeded profile squad) › `squad status--globalremoval does not break remote/dual-root or externalized statetest/external-state.test.ts,test/effective-squad-dir.test.ts,test/cli/cast.test.ts,test/cli/export-import.test.ts,test/cli/rc.test.tsunchanged and green (they stub the config dir for externalized state only)test/squad-20-host-feature-matrix.test.ts› "squad_state_health names the configured backend (orphan) …", "squad_state_list without dir lists the root …";test/squad-20-all-scenarios.e2e.test.tsR3-12test/squad-20-host-feature-matrix.test.ts› "host runtime flags agree with CAPABILITY_TOKENS_BY_HOST";test/clients.test.tscapability tokenstest/template-sync.test.ts,test/clients.test.ts› behavioral-contract parity (CANONICAL_COORDINATOR_HEADINGS)test/ux-gates.test.ts,test/cli-command-wiring.test.ts,test/cli/command-help.test.tsValidation (this head, Windows, host heavily loaded — ~690 node processes)
SKIP_BUILD_BUMP=1 npm run build✅ (clean dist; staleagents/personal.*etc. removed — the gate catches stale dist)npm run lint✅ ·npm run lint:docs✅retired-symbols, profile-squad-tombstone, cli-outside-project, resolution, resolve-cache, cross-package-exports, init-vscode-settings, template-sync, cli-command-wiring, ux-gates, squad-20-host-feature-matrix, clients, cli/command-help, cli/cast, sdk-feature-parity, external-state, effective-squad-dir, docs-build, speed-gates, template-extra-classification, cli-packaging-smoke, backend, specification-suite→ 864 passed / 35 expected fail / 0 branch-caused failures; environmental only:cli-packaging-smokebeforeAll (npm pack×2 > 90 s hook under load;npm pack --dry-runalone took 11 s),speed-gatesinit ceremony 12.8 s vs 10 s budget, twoux-gatesprocess-exit timeouts (pass alone / in CI).43dcb62c:retired-symbols, upstream-runtime, profile-squad-tombstone, cli-outside-project, upstream-source-hardening→ 75 passed / 0 failed;squad-20-all-scenarios.e2e,squad-20-real-clients-stdio.e2e→ green in the 802-passed run on the pre-rebase tree..changeset/squad2-c-personal-removal-and-fixes.md(major× 3)PR Readiness Checklist
Branch & Commit
dev(stacked: → [2/3] feat(upstream): runtime upstream inheritance with confined, race-safe snapshot reads and git source hardening (F1) #2278 → [1/3] docs+test(squad-2.0): Squad feature x host matrix with live Claude/OpenCode runs and bridge tests #2277 →dev)feat!:commit)Build & Test
npm run buildpassesnpm test— targeted suites above green; environmental timeouts listed; CI is authoritativenpm run lintpassesnpm run lint:eslintpasses (part ofnpm run lint)Changeset
.changeset/squad2-c-personal-removal-and-fixes.md)CHANGELOG.mdentry — N/Askip-changeloglabel — N/ADocs
--globalremoved); docs pages/nav removed, resolution order rewrittenExports
./agents/personaland./sharing/consultremoved;multi-squadremoved)Breaking Changes
BREAKING: Personal squads, consult mode and the global squad (
--global) were removed; existingpersonal-squad/and global.squad/directories under the user profile are no longer read or written and may be deleted manually.Also: outside a project,
squad status|doctor|cast|costnow exit non-zero with a remediation message instead of resolving a user-profile squad. SDK exports listed under How are gone.Waivers
None.
Review round (Q/Bubu/Worf final-head + Data F4) → tests
NO_SQUAD_MESSAGE/fatalNoSquad():No squad in this directory. Run "squad init" first.across every project-scoped command; economy/config private walkers replaced by the SDK resolvertest/cli-outside-project.test.ts› "every project-scoped command prints the identical canonical message, exits 1 and creates nothing (LC-9)" (11 commands, no.squadmkdir)%APPDATA%\squad/~/.config/squad/~/Library/…/squadis part of the profile boundary; boundary built by canonicalizing the parent only (never stats the retired dir)test/profile-boundary.test.ts› "the platform config dir … is never admitted as a project, at any spelling (LC-11)" — red pre-fixcanonicalDir→ null when the existing prefix cannot be realpath'ed; resolver refuses,isRetiredProfileTeamRoot→ true; unknown home refuses;.squadlink to a profile target refusedtest/setup/profile-fs-guard.cjsthrows on fs/fs.promises access under the real profile roots; inherited by children viaNODE_OPTIONS=--require+SQUAD_TEST_FORBIDDEN_ROOTStest/profile-fs-guard.test.ts(sync, callback, promise, platform config dir, child with faked HOME/APPDATA)<home>itself,SQUAD_HOME, platform config dir onlytest/profile-boundary.test.ts:<home>/src/proj, 8.3 short paths (loud skip when disabled), case/separator variants, junction to profile root, HOME/USERPROFILE/APPDATA/SQUAD_HOME variantspreflightCastingPair()beforewriteAgentTemplatein both pathstest/upgrade-profile-teamroot.test.ts› "F4: … first upgrade writes the capabilities block; the second upgrade is a byte-identical no-op" — red pre-fixRemoved obsolete "teamRoot" setting from .squad/config.json.test/retired-symbols.test.ts› "…BREAKING entry is exactly one line"git worktreeclean checkout →npm ci→ build →npm pack --dry-run×2: 0 retired files; everyexportstarget exists in dist with no allowlist (the former./shell/sdk-bridgeexemption was removed in 94e7675 after #2285 landed on dev)